package com.example.spider.task;

import com.example.spider.config.SpiderMetrics;
import org.shoulder.core.util.ContextUtils;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;

import java.util.concurrent.LinkedBlockingDeque;

/**
 * 任务队列
 * 为什么单独搞个任务队列，不直接塞到 spiderThreadPool 的队列里？
 * 为分布式扩展埋伏笔，方便替换
 *
 * @author lym
 */
public class SpiderTaskQueue {

    private static final LinkedBlockingDeque<AbstractSpiderTask<?>> blockingDeque = new LinkedBlockingDeque<>(10_0000);

    public static boolean putHighestPriorityTask(@NonNull AbstractSpiderTask<?> task) {
        if (task == null) {
            return false;
        }
        try {
            blockingDeque.putFirst(task);
            afterInQueue(task);
            return true;
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public static boolean putTask(@NonNull AbstractSpiderTask<?> task) {
        if (task == null) {
            return false;
        }
//        if(task.supportCluster() && AppInfo.cluster()) {
//            // 丢到分布式队列，以便各节点均衡
//            return ContextUtils.getBean(Sender.class).addSpiderTask(task, null);
//        }
        try {
            blockingDeque.put(task);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        afterInQueue(task);
        return true;
    }

    @Nullable
    public static AbstractSpiderTask<?> getTask() {
        AbstractSpiderTask<?> task = blockingDeque.poll();
        beforeOutQueue(task);
        return task;
    }

    private static void afterInQueue(AbstractSpiderTask<?> task) {
        if (task != null) {
            ContextUtils.getApplicationContext().getBean("spiderMetrics", SpiderMetrics.class)
                    .inQueueTask(task);
        }
    }

    private static void beforeOutQueue(AbstractSpiderTask<?> task) {
        if (task != null) {

            ContextUtils.getApplicationContext().getBean("spiderMetrics", SpiderMetrics.class)
                    .outQueueTask(task);
        }
    }

    public static int getSize() {
        return blockingDeque.size();
    }


}
